#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include "configure.h"
//#include "url_info.h"
#include "common.h"

extern void* send_404(int sock);
extern struct configure* global_conf;
struct head_info{
char flag;
char buff[2048];
char* file_name;
char* cookie;
char* qmar;
};


int http_port=8080;
char server_path[]="";
struct timeval time_out_so={20,0};
char main_path[]="";
char get_method[]="GET ";
char post_method[]="POST";
//char request_buff[4*1024];
char response_buff[1024*1024];

void* http_server();
void* socket_process(int client_so);
int print_stat(char* buff);
int read_static_file(char* path,int so);
int read_dynamic_file(char* path,int so);
int process_change(char* head_buff);
int print_form(int pro_type);
int raw_recv_header(int socket_id,char* buff,int bufflen);
int get_head_info(struct head_info *hinfo);
struct user_info
{
	u_int32_t ip;
	char host_name;
	char user_name;
};

int raw_recv_header(int socket_id, char *buff, int bufflen)
{
	int count = 6;
	int index = 0;
	int nread;
	while ( count --  && index < bufflen)
	{
		if ((nread = recv(socket_id, buff+index, bufflen-index, 0)) < 0)
		{
			return -1;
		}
		index += nread;
		if (index > 4 && *(u_int32_t*)(buff + (index-4)) == *(u_int32_t*)"\r\n\r\n")
		{
			return index;
		}
	}
	return -1;
}

int get_head_info(struct head_info *hinfo){
	char* tmp_index;
	char* head_start;

	if((tmp_index=strstr(hinfo->buff," HTTP/1"))>0) {*tmp_index=0; head_start=tmp_index+11;}
	else { hinfo->flag=0; return -1;}
	hinfo->flag=1;
	if((tmp_index=index(hinfo->buff,'?'))>0) {hinfo->qmar=tmp_index+1; *tmp_index=0;}
	else hinfo->qmar=0;
	if((tmp_index=rindex(hinfo->buff, ' '))>0) {hinfo->file_name=tmp_index+1;}
	else hinfo->file_name=0;
	if((tmp_index=strstr(head_start,"\r\nCookie: "))>0) {hinfo->cookie=tmp_index+10;}
	else hinfo->cookie=0;
	return 0;
}

void* http_server(){
	printf("start http server\r\n");
	int socket_li;
	int acc_socket;
	struct sockaddr_in http_bin_addr;
	memset(&http_bin_addr,0,sizeof(http_bin_addr));
	http_bin_addr.sin_family=AF_INET;
	http_bin_addr.sin_port=htons(http_port);
	http_bin_addr.sin_addr.s_addr=htonl(INADDR_ANY);

	if((socket_li=socket(PF_INET,SOCK_STREAM,0))<0){
		perror("socket_li buile fail\n");
		return;
	}
	if((bind(socket_li,(struct sockaddr*)&http_bin_addr,(socklen_t)sizeof(http_bin_addr)))<0){
	perror("socket bind fail\n");
	}
	if((listen(socket_li,20))<0){
		perror("socket_li listen fail\n");
		return;
	}
	while(1){
		printf("socket accepting\r\n");
		if((acc_socket=accept(socket_li,0,0))<0){
			perror("acc_socket faile\n");
			continue;
		}
		if(fork()==0){
			close(socket_li);
			socket_process(acc_socket);
			close(acc_socket);
			_exit(0);
		}else{
			close(acc_socket);
		}
	}
}

void* socket_process(int socket_client){
    struct head_info head_option;
    int recv_buff_size=0;
	while(1){
	if (setsockopt(socket_client, SOL_SOCKET,SO_SNDTIMEO, (char *)&time_out_so,sizeof(struct timeval)) < 0)
		perror("setsockopt\r\n");
	if (setsockopt(socket_client, SOL_SOCKET,SO_RCVTIMEO, (char *)&time_out_so,sizeof(struct timeval)) < 0)
		perror("setsockopt\r\n");
	if((recv_buff_size=raw_recv_header(socket_client, head_option.buff,2048))<0) return ;
	if(get_head_info(&head_option)==-1) return;
	if(strcmp((char*)(head_option.file_name+strlen(head_option.file_name)-3),".do")==0) read_dynamic_file(head_option.file_name,socket_client);
	}
}

int read_static_file(char* file_path,int so){
return 0;
}
int read_dynamic_file(char* file_path,int so){
	int i,j, b_index=0;
	char head_buff[1024]={0,};
	char content_length[28]={0,};

	memset(response_buff,0,(size_t)sizeof(response_buff));
	strcat(head_buff,"HTTP/1.1 200 Ok\r\n");
	
	for(i=0; i<(global_conf->nr_cache) ; i++){

	b_index+=sprintf(response_buff+b_index,"<div >cache ip: <a target=_blank href=http://%s:8080>%s</a>,",global_conf->node_str[i],global_conf->node_str[i]);
	b_index+=sprintf(response_buff+b_index," status: %d,",global_conf->cache_list[i].state);
	b_index+=sprintf(response_buff+b_index," disk count: %d<br/>",global_conf->cache_list[i].sys_info.np);
	b_index+=sprintf(response_buff+b_index," cpu_av1: %.2f\%,",((double)global_conf->cache_list[i].sys_info.av1)/100);
	b_index+=sprintf(response_buff+b_index," cpu_av5: %.2f\%,",((double)global_conf->cache_list[i].sys_info.av5)/100);
	b_index+=sprintf(response_buff+b_index," cpu_av15: %.2f\%<br/>",((double)global_conf->cache_list[i].sys_info.av15)/100);
	b_index+=sprintf(response_buff+b_index," cpu_us: %.2f\%,",((double)global_conf->cache_list[i].sys_info.us)/100);
	b_index+=sprintf(response_buff+b_index," cpu_ni: %.2f\%,",((double)global_conf->cache_list[i].sys_info.ni)/100);
	b_index+=sprintf(response_buff+b_index," cpu_sy: %.2f\%,",((double)global_conf->cache_list[i].sys_info.sy)/100);
	b_index+=sprintf(response_buff+b_index," cpu_id: %.2f\%<br/>",((double)global_conf->cache_list[i].sys_info.id)/100);
	b_index+=sprintf(response_buff+b_index," cpu_wa: %.2f\%,",((double)global_conf->cache_list[i].sys_info.wa)/100);
	b_index+=sprintf(response_buff+b_index," cpu_hi: %.2f\%,",((double)global_conf->cache_list[i].sys_info.hi)/100);
	b_index+=sprintf(response_buff+b_index," cpu_si: %.2f\%,",((double)global_conf->cache_list[i].sys_info.si)/100);
	b_index+=sprintf(response_buff+b_index," cpu_st: %.2f\%<br/>",((double)global_conf->cache_list[i].sys_info.st)/100);
	b_index+=sprintf(response_buff+b_index," mem_total: %dk,",global_conf->cache_list[i].sys_info.mem_tt);
	b_index+=sprintf(response_buff+b_index," mem_used: %dk,",global_conf->cache_list[i].sys_info.mem_us);
	b_index+=sprintf(response_buff+b_index," mem_free: %dk,",global_conf->cache_list[i].sys_info.mem_fr);
	b_index+=sprintf(response_buff+b_index," mem_buffer: %dk",global_conf->cache_list[i].sys_info.mem_bu);

	b_index+=sprintf(response_buff+b_index,"<table <tr><td>");
	b_index+=sprintf(response_buff+b_index,"<table border=1 cellpadding=0 cellspacing=0 bgcolor=black>");
	b_index+=sprintf(response_buff+b_index,"<tr bgcolor=white><td>mount_point</td>");
	b_index+=sprintf(response_buff+b_index,"<td>type</td><td>tatal_size</td><td>used_size</td>");
	b_index+=sprintf(response_buff+b_index,"<td>free_size</td></td></tr>");
	for(j=0;j<global_conf->cache_list[i].sys_info.np;j++){
		b_index+=sprintf(response_buff+b_index,"<tr bgcolor=white>");
		b_index+=sprintf(response_buff+b_index,"<td>%s</d>",global_conf->cache_list[i].sys_info.p[j].mount_point);
		b_index+=sprintf(response_buff+b_index,"<td>%s</d>",global_conf->cache_list[i].sys_info.p[j].type);
		b_index+=sprintf(response_buff+b_index,"<td>%dG</d>",global_conf->cache_list[i].sys_info.p[j].total);
		b_index+=sprintf(response_buff+b_index,"<td>%dG</d>",global_conf->cache_list[i].sys_info.p[j].used);
		b_index+=sprintf(response_buff+b_index,"<td>%dG</d>",global_conf->cache_list[i].sys_info.p[j].free);
		b_index+=sprintf(response_buff+b_index,"</tr>");
	}
	
	b_index+=sprintf(response_buff+b_index,"</table ></td><td valign=top>");
	b_index+=sprintf(response_buff+b_index,"<table border=1 cellpadding=0 cellspacing=0 bgcolor=black>");
	b_index+=sprintf(response_buff+b_index,"<tr bgcolor=white><td>model</td><td>serial</td><td>firmware</td></tr>");
	
	for(j=0;j<global_conf->cache_list[i].sys_info.nd;j++){
		b_index+=sprintf(response_buff+b_index,"<tr bgcolor=white>");
		b_index+=sprintf(response_buff+b_index,"<td>%s</d>",global_conf->cache_list[i].sys_info.d[j].model);
		b_index+=sprintf(response_buff+b_index,"<td>%s</d>",global_conf->cache_list[i].sys_info.d[j].serial);
		b_index+=sprintf(response_buff+b_index,"<td>%s</d>",global_conf->cache_list[i].sys_info.d[j].firmware);
		b_index+=sprintf(response_buff+b_index,"</tr>");
	}
	b_index+=sprintf(response_buff+b_index,"</table>");
	b_index+=sprintf(response_buff+b_index,"</td></tr></table></div><br/>");
	}
	sprintf(content_length,"Content-Length: %d\r\n",strlen(response_buff));
    strcat(head_buff,content_length);
	strcat(head_buff,"\r\n");
	send(so,head_buff,strlen(head_buff),0);
	send(so,response_buff,strlen(response_buff),0);
	return 0;
}
int process_change(char* head_buff){
return 0;
}
